package com.topsun.framework.common.core.util;

import cn.hutool.core.codec.Base64;
import cn.hutool.crypto.ProviderFactory;

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.security.AlgorithmParameters;
import java.security.Key;
import java.security.Security;

/**
 * @author: 皮皮
 * @date: 2020/8/31 9:28 PM
 */
public class AesUtil {


    /**
     *  算法名
     */
    private static final String KEY_NAME = "AES";
    /**
     * 加解密算法/模式/填充方式
     * ECB模式只用密钥即可对数据进行加密解密，CBC模式需要添加一个iv
     */
    private static final String CIPHER_ALGORITHM = "AES/CBC/PKCS7Padding";

    /**
     * 微信 数据解密<br/>
     * 对称解密使用的算法为 AES-128-CBC，数据采用PKCS#7填充<br/>
     * 对称解密的目标密文:encrypted=Base64_Decode(encryptData)<br/>
     * 对称解密秘钥:key = Base64_Decode(session_key),aeskey是16字节<br/>
     * 对称解密算法初始向量:iv = Base64_Decode(iv),同样是16字节<br/>
     *
     * @param encrypted 目标密文
     * @param sessionKey 会话ID
     * @param iv 加密算法的初始向量
     */
    public static String wxDecrypt(String encrypted, String iv, String sessionKey) throws Exception {
        byte[] encrypted64 = Base64.decode(encrypted);
        byte[] key64 = Base64.decode(sessionKey);
        byte[] iv64 = Base64.decode(iv);
        init();
        return new String(decrypt(encrypted64, key64, generateIV(iv64)));
    }

    /**
     * 初始化密钥
     */
    private static void init() throws Exception {
        Security.addProvider(ProviderFactory.createBouncyCastleProvider());
        KeyGenerator.getInstance(KEY_NAME).init(128);
    }

    /**
     * 生成iv
     */
    private static AlgorithmParameters generateIV(byte[] iv) throws Exception {
        // iv 为一个 16 字节的数组，这里采用和 iOS 端一样的构造方法，数据全为0
        AlgorithmParameters params = AlgorithmParameters.getInstance(KEY_NAME);
        params.init(new IvParameterSpec(iv));
        return params;
    }

    /**
     * 生成解密
     */
    private static byte[] decrypt(byte[] encryptedData, byte[] keyBytes, AlgorithmParameters iv)
            throws Exception {
        Key key = new SecretKeySpec(keyBytes, KEY_NAME);
        Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
        // 设置为解密模式
        cipher.init(Cipher.DECRYPT_MODE, key, iv);
        return cipher.doFinal(encryptedData);
    }

    public static void main(String[] args) throws Exception {
        String encryptedData = "MSHwnh1FYRbIJXAXn5vUuANqDukf539cieGScwt3iWPNOrP6GL9AXHaAmCAy04IXPDGfsUNGUFhCndn+7L6JwlE36k1VjS9czivVvIQxRtoe6nbSOQL2+wKz0WCNPHFtc36OJdDqpOVBC+k1g8ajUNxDA5GzyrNV7Lq6souzmrte76E638jVNi9jIFnGGw3CCsPMmkL9/f1VHoGwsoGwcw==";
        String sessionKey = "7fa8Eaf1Ba4RN7fKY04cbg==";
        String iv = "zxDuv20vBxbyLW1GyS7jcw==";
        String decrypt = wxDecrypt(encryptedData, iv, sessionKey);
        System.out.println(decrypt);

    }
}
